SPDX-FileCopyrightText: 2021 Dina El Khattabi & Ayman Ouiriarhli Ameur SPDX-FileCopyrightText: 2024 AlICe laboratory https://alicelab.be
SPDX-License-Identifier: GPL-3.0-or-later
Developped in Blender 2.93.4
Solo for Voice 45
Joan LA BARBARA (composed by John CAGE)
EL KHATTABI Dina & OUIRIARHLI AMEUR Ayman
Libraries import
import bpy
import re
import random
from random import randint, shuffle, uniform
from copy import deepcopy
from math import sin, cos, piCleaning the scene
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete()
bpy.ops.outliner.orphans_purge()def get_objects(name):
res = []
for obj in bpy.data.objects:
if name in obj.name:
res.append(obj)
return resdef apply_modifiers(obj):
ctx = bpy.context.copy()
ctx["object"] = obj
for _, m in enumerate(obj.modifiers):
try:
ctx["modifier"] = m
bpy.ops.object.modifier_apply(ctx, modifier=m.name)
except RuntimeError:
print(f"Error applying {m.name} to {obj.name}, removing it instead.")
obj.modifiers.remove(m)
for m in obj.modifiers:
obj.modifiers.remove(m)def bool(obj1, obj2, type="INTERSECT"):
bool = obj2.modifiers.new(name="booly", type="BOOLEAN")
bool.object = obj1
bool.operation = typedef multi_boolean(collection, object, type):
for element in collection:
bool(object, element, type)DEFINING A REFERENCE PAGE (GROUP)
PAGE = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"PAGE0",
]
SUBLIST = PAGE[0:5]DEFINIG THE EIGHTEEN PAGES
PAGE1 = deepcopy(PAGE)
PAGE1[0][0] = 1
PAGE1[0][1] = 1
PAGE1[0][2] = 1
shuffle(PAGE1[0])
PAGE1[1][0] = 1
PAGE1[1][1] = 1
PAGE1[1][2] = 1
shuffle(PAGE1[1])
PAGE1[2][0] = 1
PAGE1[2][1] = 1
PAGE1[2][2] = 1
shuffle(PAGE1[2])
PAGE1[3][0] = 1
shuffle(PAGE1[3])
PAGE1[4][0] = 1
PAGE1[4][1] = 1
PAGE1[4][2] = 1
shuffle(PAGE1[4])
PAGE1[5][0] = 1
PAGE1[5][1] = 1
PAGE1[5][2] = 1
PAGE1[5][4] = 1
PAGE1[-1] = "PAGE1"
shuffle(PAGE1[5])PAGE2 = deepcopy(PAGE)
PAGE2[0][0] = 1
PAGE2[0][1] = 1
PAGE2[0][2] = 1
PAGE2[0][3] = 1
shuffle(PAGE2[0])
PAGE2[1][0] = 1
shuffle(PAGE2[1])
PAGE2[2][0] = 1
PAGE2[2][1] = 1
shuffle(PAGE2[2])
PAGE2[3][0] = 1
PAGE2[3][1] = 1
PAGE2[3][2] = 1
shuffle(PAGE2[3])
PAGE2[4][0] = 1
PAGE2[4][1] = 1
shuffle(PAGE2[4])
PAGE2[5][0] = 1
PAGE2[-1] = "PAGE2"
shuffle(PAGE2[5])PAGE3 = deepcopy(PAGE)
PAGE3[0][0] = 1
PAGE3[0][1] = 1
shuffle(PAGE3[0])
PAGE3[1][0] = 1
PAGE3[1][1] = 1
PAGE3[1][2] = 1
shuffle(PAGE3[1])
PAGE3[2][0] = 1
PAGE3[2][1] = 1
PAGE3[2][2] = 1
shuffle(PAGE3[2])
PAGE3[3][0] = 1
PAGE3[3][1] = 1
shuffle(PAGE3[3])
PAGE3[4][0] = 1
PAGE3[4][1] = 1
PAGE3[4][2] = 1
shuffle(PAGE3[4])
PAGE3[5][0] = 1
PAGE3[5][1] = 1
PAGE3[5][2] = 1
PAGE3[-1] = "PAGE3"
shuffle(PAGE3[5])PAGE4 = deepcopy(PAGE)
PAGE4[0][0] = 1
PAGE4[0][1] = 1
PAGE4[0][2] = 1
PAGE4[0][3] = 1
PAGE4[0][4] = 1
shuffle(PAGE4[0])
PAGE4[1][0] = 1
shuffle(PAGE4[1])
PAGE4[2][0] = 1
PAGE4[2][1] = 1
shuffle(PAGE4[2])
PAGE4[3][0] = 1
PAGE4[3][1] = 1
shuffle(PAGE4[3])
PAGE4[4][0] = 1
PAGE4[4][1] = 1
PAGE4[4][2] = 1
PAGE4[4][3] = 1
shuffle(PAGE4[4])
PAGE4[5][0] = 1
PAGE4[5][1] = 1
PAGE4[5][2] = 1
PAGE4[5][3] = 1
PAGE4[-1] = "PAGE4"
shuffle(PAGE4[5])PAGE5 = deepcopy(PAGE)
PAGE5[0][0] = 1
shuffle(PAGE5[0])
PAGE5[1][0] = 1
PAGE5[1][1] = 1
PAGE5[1][2] = 1
PAGE5[1][3] = 1
shuffle(PAGE5[1])
PAGE5[2][0] = 1
PAGE5[2][1] = 1
PAGE5[2][2] = 1
PAGE5[2][3] = 1
shuffle(PAGE5[2])
PAGE5[3][0] = 1
PAGE5[3][1] = 1
shuffle(PAGE5[3])
PAGE5[4][0] = 1
PAGE5[4][1] = 1
PAGE5[4][2] = 1
shuffle(PAGE5[4])
PAGE5[5][0] = 1
PAGE5[5][1] = 1
PAGE5[5][2] = 1
PAGE5[5][3] = 1
PAGE5[-1] = "PAGE5"
shuffle(PAGE5[5])PAGE6 = deepcopy(PAGE)
PAGE6[0][0] = 1
PAGE6[0][1] = 1
shuffle(PAGE6[0])
PAGE6[2][0] = 1
shuffle(PAGE6[2])
PAGE6[3][0] = 1
shuffle(PAGE6[3])
PAGE6[4][0] = 1
PAGE6[4][1] = 1
shuffle(PAGE6[4])
PAGE6[5][0] = 1
PAGE6[-1] = "PAGE6"
shuffle(PAGE6[5])PAGE7 = deepcopy(PAGE)
PAGE7[0][0] = 1
PAGE7[0][1] = 1
shuffle(PAGE7[0])
PAGE7[1][0] = 1
PAGE7[1][1] = 1
PAGE7[1][2] = 1
PAGE7[1][3] = 1
shuffle(PAGE7[1])
PAGE7[2][0] = 1
PAGE7[2][1] = 1
shuffle(PAGE7[2])
PAGE7[3][0] = 1
shuffle(PAGE7[3])
PAGE7[4][0] = 1
PAGE7[4][1] = 1
shuffle(PAGE7[4])
PAGE7[5][0] = 1
PAGE7[5][1] = 1
PAGE7[5][2] = 1
PAGE7[-1] = "PAGE7"
shuffle(PAGE7[5])PAGE8 = deepcopy(PAGE)
PAGE8[0][0] = 1
shuffle(PAGE8[0])
PAGE8[1][0] = 1
PAGE8[1][1] = 1
PAGE8[1][2] = 1
shuffle(PAGE8[1])
PAGE8[2][0] = 1
PAGE8[2][1] = 1
PAGE8[2][2] = 1
shuffle(PAGE8[2])
PAGE8[3][0] = 1
PAGE8[3][1] = 1
PAGE8[3][2] = 1
PAGE8[3][3] = 1
shuffle(PAGE8[3])
PAGE8[4][0] = 1
shuffle(PAGE8[4])
PAGE8[5][0] = 1
PAGE8[-1] = "PAGE8"
shuffle(PAGE8[5])PAGE9 = deepcopy(PAGE)
PAGE9[0][0] = 1
PAGE9[0][1] = 1
shuffle(PAGE9[0])
PAGE9[1][0] = 1
PAGE9[1][1] = 1
PAGE9[1][2] = 1
PAGE9[1][3] = 1
shuffle(PAGE9[1])
PAGE9[2][0] = 1
PAGE9[2][1] = 1
PAGE9[2][2] = 1
PAGE9[2][3] = 1
PAGE9[2][4] = 1
shuffle(PAGE9[2])
PAGE9[3][0] = 1
PAGE9[3][1] = 1
PAGE9[3][2] = 1
PAGE9[3][3] = 1
shuffle(PAGE9[3])
PAGE9[4][0] = 1
PAGE9[4][1] = 1
PAGE9[4][2] = 1
PAGE9[4][3] = 1
shuffle(PAGE9[4])
PAGE9[5][0] = 1
PAGE9[5][1] = 1
PAGE9[5][2] = 1
PAGE9[-1] = "PAGE9"
shuffle(PAGE9[5])PAGE10 = deepcopy(PAGE)
PAGE10[1][0] = 1
PAGE10[1][1] = 1
PAGE10[1][2] = 1
shuffle(PAGE10[1])
PAGE10[2][0] = 1
PAGE10[2][1] = 1
shuffle(PAGE10[2])
PAGE10[3][0] = 1
PAGE10[3][0] = 1
shuffle(PAGE10[3])
PAGE10[4][0] = 1
PAGE10[4][1] = 1
shuffle(PAGE10[4])
PAGE10[5][0] = 1
PAGE10[-1] = "PAGE10"
shuffle(PAGE10[5])PAGE11 = deepcopy(PAGE)
PAGE11[0][0] = 1
shuffle(PAGE11[0])
PAGE11[1][0] = 1
PAGE11[1][1] = 1
shuffle(PAGE11[1])
PAGE11[2][0] = 1
shuffle(PAGE11[2])
PAGE11[3][0] = 1
shuffle(PAGE11[3])
PAGE11[4][0] = 1
PAGE11[4][1] = 1
shuffle(PAGE11[4])
PAGE11[5][0] = 1
PAGE11[5][1] = 1
PAGE11[5][2] = 1
PAGE11[-1] = "PAGE11"
shuffle(PAGE11[5])PAGE12 = deepcopy(PAGE)
PAGE12[0][0] = 1
PAGE12[0][1] = 1
PAGE12[0][2] = 1
PAGE12[0][3] = 1
PAGE12[0][4] = 1
shuffle(PAGE12[0])
PAGE12[1][0] = 1
PAGE12[1][1] = 1
PAGE12[1][2] = 1
PAGE12[1][3] = 1
shuffle(PAGE12[1])
PAGE12[2][0] = 1
PAGE12[2][1] = 1
PAGE12[2][2] = 1
PAGE12[2][3] = 1
PAGE12[2][4] = 1
shuffle(PAGE12[2])
PAGE12[3][0] = 1
PAGE12[3][2] = 1
PAGE12[3][3] = 1
shuffle(PAGE12[3])
PAGE12[4][0] = 1
PAGE12[4][1] = 1
shuffle(PAGE12[4])
PAGE12[5][0] = 1
PAGE12[-1] = "PAGE12"
shuffle(PAGE12[5])PAGE13 = deepcopy(PAGE)
PAGE13[0][0] = 1
PAGE13[0][1] = 1
PAGE13[0][2] = 1
shuffle(PAGE13[0])
PAGE13[1][0] = 1
PAGE13[1][1] = 1
PAGE13[1][2] = 1
PAGE13[1][3] = 1
shuffle(PAGE13[1])
PAGE13[2][0] = 1
shuffle(PAGE13[2])
PAGE13[3][0] = 1
PAGE13[3][2] = 1
PAGE13[3][3] = 1
PAGE13[3][4] = 1
shuffle(PAGE13[3])
PAGE13[4][0] = 1
PAGE13[4][1] = 1
shuffle(PAGE13[4])
PAGE13[5][0] = 1
PAGE13[5][1] = 1
PAGE13[5][2] = 1
PAGE13[5][3] = 1
PAGE13[-1] = "PAGE13"
shuffle(PAGE13[5])PAGE14 = deepcopy(PAGE)
PAGE14[0][0] = 1
PAGE14[0][1] = 1
shuffle(PAGE14[0])
PAGE14[1][0] = 1
PAGE14[1][1] = 1
PAGE14[1][2] = 1
PAGE14[1][3] = 1
shuffle(PAGE14[1])
PAGE14[2][0] = 1
PAGE14[2][1] = 1
PAGE14[2][2] = 1
shuffle(PAGE14[2])
PAGE14[3][0] = 1
PAGE14[3][2] = 1
shuffle(PAGE14[3])
PAGE14[4][0] = 1
PAGE14[4][1] = 1
PAGE14[4][3] = 1
PAGE14[4][4] = 1
shuffle(PAGE14[4])
PAGE14[5][0] = 1
PAGE14[5][1] = 1
PAGE14[-1] = "PAGE14"
shuffle(PAGE14[5])PAGE15 = deepcopy(PAGE)
PAGE15[0][0] = 1
PAGE15[0][1] = 1
shuffle(PAGE15[0])
PAGE15[1][0] = 1
PAGE15[1][1] = 1
shuffle(PAGE15[1])
PAGE15[3][0] = 1
PAGE15[3][2] = 1
shuffle(PAGE15[3])
PAGE15[4][0] = 1
PAGE15[4][1] = 1
PAGE15[4][3] = 1
PAGE15[4][4] = 1
shuffle(PAGE15[4])
PAGE15[5][0] = 1
PAGE15[5][1] = 1
PAGE15[5][2] = 1
PAGE15[-1] = "PAGE15"
shuffle(PAGE15[5])PAGE16 = deepcopy(PAGE)
PAGE16[0][0] = 1
PAGE16[0][1] = 1
shuffle(PAGE16[0])
PAGE16[1][0] = 1
PAGE16[1][1] = 1
shuffle(PAGE16[1])
PAGE16[2][0] = 1
PAGE16[2][1] = 1
PAGE16[2][2] = 1
shuffle(PAGE16[2])
PAGE16[3][0] = 1
shuffle(PAGE16[3])
PAGE16[4][0] = 1
shuffle(PAGE16[4])
PAGE16[5][0] = 1
PAGE16[-1] = "PAGE16"
shuffle(PAGE16[5])PAGE17 = deepcopy(PAGE)
PAGE17[0][0] = 1
PAGE17[0][1] = 1
PAGE17[0][2] = 1
PAGE17[0][3] = 1
shuffle(PAGE17[0])
PAGE17[1][0] = 1
PAGE17[1][1] = 1
PAGE17[1][2] = 1
PAGE17[1][3] = 1
shuffle(PAGE17[1])
PAGE17[2][0] = 1
PAGE17[2][1] = 1
PAGE17[2][2] = 1
shuffle(PAGE17[2])
PAGE17[3][0] = 1
PAGE17[3][1] = 1
PAGE17[3][2] = 1
PAGE17[3][3] = 1
PAGE17[3][4] = 1
shuffle(PAGE17[3])
PAGE17[4][0] = 1
PAGE17[4][1] = 1
shuffle(PAGE17[4])
PAGE17[5][0] = 1
PAGE17[5][1] = 1
PAGE17[-1] = "PAGE17"
shuffle(PAGE17[5])PAGE18 = deepcopy(PAGE)
PAGE18[0][0] = 1
PAGE18[0][1] = 1
shuffle(PAGE18[0])
PAGE18[1][0] = 1
shuffle(PAGE18[1])
PAGE18[2][0] = 1
shuffle(PAGE18[2])
PAGE18[3][0] = 1
shuffle(PAGE18[3])
PAGE18[4][0] = 1
PAGE18[4][1] = 1
shuffle(PAGE18[4])
PAGE18[5][0] = 1
PAGE18[-1] = "PAGE18"
shuffle(PAGE18[5])DEFINING THE LISTOF THE ORIGINAL COMPOSITION (John CAGE’s)
COMPOSITION = [
PAGE1,
PAGE2,
PAGE3,
PAGE4,
PAGE5,
PAGE6,
PAGE7,
PAGE8,
PAGE9,
PAGE10,
PAGE11,
PAGE12,
PAGE13,
PAGE14,
PAGE15,
PAGE16,
PAGE17,
PAGE18,
]CONSOLE INFOS
print(75 * "/", " C O D E L A U N C H ", 75 * "/")SUFFLE IN PAGES
shuffle(SUBLIST)print (str in PAGE,’:’, SUBLIST)
NEW COMPOSITION (PICKING RANDOM PAGES)
shuffle(COMPOSITION)
n = randint(1, 10)
NEW_COMPOSITION = COMPOSITION[:n]CONSOLE INFOS
print("Number of pages picked", n)
print(200 * "=")
print("ORIGINAL HEIGHTS OF EACH PAGE")Assigning points to polar coordinates
web = []
for lvl in range(1, n + 1):
ZPage = (9 / n) * lvl
print("Zpage", lvl, "=", ZPage)
print(75 * "-")
Niveaux = []
for rayon in range(2, 8):
cercle = []
for rotation in range(1, 13):
result = (
round(cos(pi / 6 * rotation) * rayon, 4),
round(sin(pi / 6 * rotation) * rayon, 4),
round(ZPage + random.uniform(-2, 2), 4),
)
cercle.append(result)
Niveaux.append(cercle)
web.append(Niveaux)CONSOLE INFOS
print(200 * "=")
print("ORIGINAL PAGES CONSTITUTING THE NEW COMPOSITION")
chips = []
for k, page in enumerate(NEW_COMPOSITION):
for j, phrase in enumerate(page):
if type(phrase) == str:CONSOLE INFOS
print(phrase)
print(75 * "-")
continue
else: # integer
ligne = []
for i, fragment in enumerate(phrase):
if fragment == 1:
ligne.append(web[k][j][i])
if ligne:
chips.append(ligne)CONSOLE INFOS
print(200 * "=")
print("POLAR COORDINATES OF THE CHIPS")
for chip in chips:
if len(chip) > 2:CONSOLE INFOS
print("chip", chip)Vertices Linked
Faces = [tuple([i for i in range(0, len(chip))])]
if len(chip) > 2:CONSOLE INFOS
print("faces", Faces)
print(75 * "-")CREATING THE MESH AND OBJECT
MESHdeChip = bpy.data.meshes.new("Layer")
monObjetChip = bpy.data.objects.new("Chip", MESHdeChip)LINK THE OBJECT TO A COLLECTION
JLB = bpy.context.collection
JLB.objects.link(monObjetChip)INJECT INFOS
MESHdeChip.from_pydata(chip, [], Faces)
all_chips = get_objects("Chip")AMBIGUITY
for obj in all_chips:First deformation (Subsurf)
mod = bpy.data.objects[obj.name].modifiers.new(name="subsurf", type="SUBSURF")
mod.levels = 6Second deformation (Solidify)
mod2 = bpy.data.objects[obj.name].modifiers.new(name="solidify", type="SOLIDIFY")
mod2.thickness = 0.05Third deformation (Wave)
mod3 = bpy.data.objects[obj.name].modifiers.new(name="wave", type="WAVE")
for chip in all_chips:
apply_modifiers(chip)The RAW model is obtained by the script above, although three further options are available for advanced results. NOTICE / Please activate one at a time and toggle comment the others. (from Start line to End) / Common part should always be activated for this part of the script.
COMMON PART OF THE THREE, SEPARATING THE VARIABLES
Boolean : intersect
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 5), scale=(5, 5, 5))
cube = get_objects("Cube")[0]
bpy.ops.object.select_all(action="DESELECT")Duplicating and renaming
for chip in all_chips:
chip.select_set(True)
bpy.ops.object.duplicate_move()
all_duplicated_chips = bpy.context.selected_objects[:]
bpy.ops.object.select_all(action="DESELECT")make and apply intersection and difference
multi_boolean(all_chips, cube, "INTERSECT")
multi_boolean(all_duplicated_chips, cube, "DIFFERENCE")
for chip in all_chips:
apply_modifiers(chip)
for chip in all_duplicated_chips:
apply_modifiers(chip)
bpy.ops.object.select_all(action="DESELECT")
cube.select_set(True)
bpy.ops.object.delete(use_global=False)CONSOLE INFOS
print(200 * "=")
print("CHIPS EXCEEDING THE SQUARE LIMITS ARE")
print(all_duplicated_chips)
print(200 * "=")All duplicated chips TO Ext
Ext = all_duplicated_chipsfor chip in Ext : mod2 = bpy.data.objects[chip.name].modifiers.new(name=’wireframe’,type=’WIREFRAME’)
START 2
CONSOLE INFOS
print("SCENARIO 2 : SIMPLE WIREFRAME")
print(75 * "-")
for chip in Ext:
chip.select_set(True)
chip.name = "Ext"
bpy.context.view_layer.objects.active = chipmake independent objects
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.separate(type="LOOSE")
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.select_all(action="DESELECT")Changing chips origin
for chip in Ext:
if "Chip" not in chip.name:
bpy.ops.object.select_all(action="DESELECT")
chip.select_set(True)
bpy.ops.object.origin_set(type="ORIGIN_GEOMETRY", center="MEDIAN")
bpy.ops.object.select_all(action="DESELECT")CONSOLE INFOS
print("(ELEMENTS USED FOR THE BOOLEAN)")Multiplyig, extruding, boolean and deleting
for chip in Ext:
bpy.ops.object.select_all(action="DESELECT")
chip.select_set(True)
bpy.ops.object.duplicate_move()
Int = bpy.context.selected_objects[:]
for item in Int:
item.name = "Int"
item.scale = (0.8, 0.8, 0.8)
mod5 = bpy.data.objects[item.name].modifiers.new(
name="displace", type="DISPLACE"
)
mod5.strength = 0.1
bool(item, chip, type="DIFFERENCE")
apply_modifiers(item)
apply_modifiers(chip)
bpy.ops.object.select_all(action="DESELECT")
item.select_set(True)
bpy.ops.object.delete(use_global=False)END 2
RENDER ON TRIMETRIC CAMERA (Alice Add-on) NOTICE: Press 0 for view - F12 for render
Camera settings
bpy.ops.object.select_all(action="DESELECT")
bpy.ops.object.camera_add(
enter_editmode=False,
align="VIEW",
location=(10, -15, 15),
rotation=(1.20428, -3.0689e-07, 0.572468),
scale=(1, 1, 1),
)
Camera = bpy.context.selected_objects
bpy.context.object.data.type = "ORTHO"
bpy.context.object.data.ortho_scale = 34
bpy.ops.transform.translate(
value=(-0.135402, 4.87448, 2.38419e-07),
orient_type="VIEW",
orient_matrix=(
(0.829038, 0.559193, -1.49012e-08),
(-0.218494, 0.323931, 0.920505),
(0.51474, -0.763133, 0.390731),
),
orient_matrix_type="VIEW",
mirror=True,
use_proportional_edit=False,
proportional_edit_falloff="SMOOTH",
proportional_size=1,
use_proportional_connected=False,
use_proportional_projected=False,
)
bpy.ops.transform.translate(
value=(-0, -0, -8.00048),
orient_type="GLOBAL",
orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)),
orient_matrix_type="GLOBAL",
constraint_axis=(False, False, True),
mirror=True,
use_proportional_edit=False,
proportional_edit_falloff="SMOOTH",
proportional_size=1,
use_proportional_connected=False,
use_proportional_projected=False,
)Reference (Cubic Frame)
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 5), scale=(5, 5, 5))
Reference = get_objects("Cube")[0]
Reference.name = "Reference"
Wireframe = bpy.data.objects[Reference.name].modifiers.new(
name="wireframe", type="WIREFRAME"
)
Wireframe.thickness = 0.1
apply_modifiers(Reference)
bpy.ops.object.select_all(action="DESELECT")Activate when needing a reference for drawing
Reference.select_set(True)
bpy.ops.object.delete(use_global=False)bpy.context.space_data.params.filename = n
EXPERIMENTING ANIMATION
CONSOLE INFOS
print(75 * "/", " C O D E E N D ", 75 * "/")